/**
 *******************************************************************************************************************************************
 * @file        posix_fsm.h
 * @brief       有限状态机实现
 * @details     /
 * @since       Change Logs:
 * Date         Author       Notes
 * 2022-12-08   lzh          the first version
 * @remark      使用方法 :
 *
 * 1.依据用户需求, 建立 fsm_event_handle 表, 枚举事件/状态;
 *
 * 2.创建 fsm_t 对象, 并将 fsm_event_handle 与之绑定;
 *
 * 3.根据用户程序需求设定不同 event 以调用 fsm_event_exec() 执行对应动作;
 *
 * 约定 <当前状态 + 一个事件> 只能有一个 动作回调 ,一般会设置一个事件为特权级事件(常用于挂起)
 *******************************************************************************************************************************************
 * @attention
 *
 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
 * -ECTION WITH THEIR PRODUCTS.
 *
 * @copyright   2012 Synwit Technology
 *******************************************************************************************************************************************
 */
#ifndef __POSIX_FSM_H__
#define __POSIX_FSM_H__

#include <stdint.h>
#include <stddef.h>

#include "pthread_lock.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef enum {
    FSM_RT_OK = 0,  /**< 成功 */
    FSM_VIE_LOCK,   /**< 竞争锁 */
    FSM_GO_TRAP,    /**< 陷入陷阱 */
    FSM_UNKNOWN     /**< 未知错误 */
}fsm_result;        /**< 状态返回值 */

/**
 * @brief   触发事件执行动作回调
 * @param   void *  : 事件参数
 * @retval  int     : 转移状态
 */
typedef int (*fsm_event_cb)(void *);

typedef struct {
    int cur_state;          /**< 当前状态 */
    int trigger_event;      /**< 触发事件 */
    fsm_event_cb do_action; /**< 动作回调(如未定义-即NULL, 则表示当前事件无动作, 直接转移状态) */
    int next_state;         /**< 转移状态 */
}fsm_handle_t;              /**< 事件处理/状态转移 */


typedef struct {
    int state;              /**< 维护状态变量 */
    fsm_handle_t *table;    /**< 状态迁移表 */
    unsigned int table_num; /**< 状态迁移表大小 */
    pthread_mutex_t mutex;  /**< 互斥锁保持访问状态变量的原子性 */
}fsm_t;                     /**< 状态机控制结构 */

/**
 * @brief       获取当前状态
 * @param [in]  fsm   : 状态机句柄
 * @param [in]  state : 当前状态
 * @retval      详见 fsm_result 枚举
 */
fsm_result fsm_state_get(fsm_t *fsm, int *state);

/**
 * @brief       切换当前状态
 * @param [in]  fsm   : 状态机句柄
 * @param [in]  state : 期望状态
 * @retval      详见 fsm_result 枚举
 */
fsm_result fsm_state_set(fsm_t *fsm, int state);

/**
 * @brief       通过该方法获取在当前状态下, 指定事件到来时的对应动作处理回调
 * @param [in]  fsm          : 状态机句柄
 * @param [in]  event        : 触发事件
 * @param [in]  fsm_event_cb : 动作执行回调
 * @retval      详见 fsm_result 枚举
 */
fsm_result fsm_event_handler_get(fsm_t *fsm, int event, fsm_event_cb *action);

/**
 * @brief       当指定事件触发时, 状态机会自动寻找并调用对应的动作处理回调, 从而完成状态转移
 * @param [in]  fsm   : 状态机句柄
 * @param [in]  event : 触发事件
 * @param [in]  data  : 事件参数
 * @retval      详见 fsm_result 枚举
 */
fsm_result fsm_event_exec(fsm_t *fsm, int event, void *data);

#ifdef __cplusplus
}
#endif

#endif //__POSIX_FSM_H__
